package com.demo.study.thread.CompletableFutures;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author baymax
 * @since 2025-05-23
 */
public class Demo1 {
    private static final ExecutorService executor = Executors.newFixedThreadPool(5);
    public static void main(String[] args) throws Exception {
        test5();

        executor.shutdown();
    }

    private static void test5() throws InterruptedException, ExecutionException {
        CompletableFuture<Integer> futureStart = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步执行1，线程id：" + Thread.currentThread().getId());
            return 1;
        }, executor);
        CompletableFuture<Integer> futureSec = futureStart.thenApply(num -> {
            System.out.println("异步执行2，thenApply线程id：" + Thread.currentThread().getId());
            return num * 2;
        });
        CompletableFuture<Integer> futureThird = futureStart.thenApplyAsync(num -> {
            System.out.println("异步执行3，thenApplyAsync线程id：" + Thread.currentThread().getId());
            return num * 3;
        }, executor);
        System.out.println(futureSec.get());
        System.out.println(futureThird.get());
    }

    private static void test4() {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("异步执行，线程id：" + Thread.currentThread().getId());
        }, executor); // 指定线程池
        future.join(); // 等待异步线程执行完成
        System.out.println("主线程id: " + Thread.currentThread().getId());
    }

    /**
     * runAsync 无返回值，且可以指定线程池
     */
    private static void test3() {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("异步执行，线程id：" + Thread.currentThread().getId());
        });
        future.join(); // 等待异步线程执行完成
        System.out.println("主线程id: " + Thread.currentThread().getId());
    }

    /**
     * 有返回值，且可以指定线程池
     */
    private static void test2() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步执行，线程id：" + Thread.currentThread().getId());
            return "异步执行结果";
        }, executor); // 指定线程池

        System.out.println("主线程id: " + Thread.currentThread().getId() + ", 异步执行结果：" + future.get());
    }

    /**
     * supplyAsync 有返回值
     * 该方法演示了如何使用CompletableFuture来异步执行一段代码，并在主线程中获取执行结果
     */
    private static void test1() throws InterruptedException, ExecutionException {
        // 创建一个CompletableFuture对象，用于异步执行一段代码
        // 使用默认的线程池（ForkJoinPool）来执行异步任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 在异步任务中，打印当前线程的ID
            System.out.println("异步执行，线程id：" + Thread.currentThread().getId());
            // 异步任务完成，返回结果
            return "异步执行结果";
        }); // 使用默认线程池

        // 主线程阻塞，等待异步任务完成，并获取结果
        String result = future.get();
        // 在主线程中，打印当前线程ID和异步任务的结果
        System.out.println("主线程id: " + Thread.currentThread().getId() + ", 异步执行结果：" + result);
    }

}
